#include <modules\graphics\transformable.h>

namespace DelGE
{
	namespace Modules
	{
		namespace Graphics
		{
			Transformable::Transformable()
			{
				this->oPosition = Vector3::Zero();
				this->oScale = Vector3::Zero();
				this->oRotation = Vector3::Zero();
			}

			Transformable::~Transformable()
			{
			}

			void Transformable::SetPosition(float fX, float fY, float fZ)
			{
				this->SetPositionX(fX);
				this->SetPositionY(fY);
				this->SetPositionZ(fZ);
			}

			void Transformable::SetPosition(const Vector3 &rPosition)
			{
				this->oPosition = rPosition;
			}

			void Transformable::SetPositionX(float fX)
			{
				this->oPosition[0] = fX;
			}

			void Transformable::SetPositionY(float fY)
			{
				this->oPosition[1] = fY;
			}

			void Transformable::SetPositionZ(float fZ)
			{
				this->oPosition[2] = fZ;
			}

			Vector3 Transformable::GetPosition()
			{
				return this->oPosition;
			}

			float Transformable::GetPositionX()
			{
				return this->oPosition[0];
			}

			float Transformable::GetPositionY()
			{
				return this->oPosition[1];
			}

			float Transformable::GetPositionZ()
			{
				return this->oPosition[2];
			}

			void Transformable::SetRotation(float fPitch, float fYaw, float fRoll)
			{
				this->SetPitch(fPitch);
				this->SetYaw(fYaw);
				this->SetRoll(fRoll);
			}

			void Transformable::SetRotation(const Vector3 &rRotation)
			{
				this->oRotation = rRotation;
			}

			void Transformable::SetPitch(float fPitch)
			{
				this->oRotation[0] = fPitch;
			}

			void Transformable::SetYaw(float fYaw)
			{
				this->oRotation[1] = fYaw;
			}

			void Transformable::SetRoll(float fRoll)
			{
				this->oRotation[2] = fRoll;
			}

			Vector3 Transformable::GetRotation()
			{
				return this->oRotation;
			}

			float Transformable::GetPitch()
			{
				return this->oRotation[0];
			}

			float Transformable::GetYaw()
			{
				return this->oRotation[1];
			}

			float Transformable::GetRoll()
			{
				return this->oRotation[2];
			}

			void Transformable::SetScale(float fX, float fY, float fZ)
			{
				this->SetScaleX(fX);
				this->SetScaleY(fY);
				this->SetScaleZ(fZ);
			}

			void Transformable::SetScale(const Vector3 &rScale)
			{
				this->oScale = rScale;
			}

			void Transformable::SetScaleX(float fX)
			{
				this->oScale[0] = fX;
			}

			void Transformable::SetScaleY(float fY)
			{
				this->oScale[1] = fY;
			}

			void Transformable::SetScaleZ(float fZ)
			{
				this->oScale[2] = fZ;
			}

			Vector3 Transformable::GetScale()
			{
				return this->oScale;
			}

			float Transformable::GetScaleX()
			{
				return this->oScale[0];
			}

			float Transformable::GetScaleY()
			{
				return this->oScale[1];
			}

			float Transformable::GetScaleZ()
			{
				return this->oScale[2];
			}

			void Transformable::Translate(float fX, float fY, float fZ)
			{
				this->oPosition = this->oPosition * Matrix::Create3DTranslation(fX, fY, fZ);
			}

			void Transformable::Move(float fX, float fY, float fZ)
			{
				Matrix transformation;

				transformation = transformation * Matrix::CreateRotationYaw(this->oRotation[1]);
				transformation = transformation * Matrix::CreateRotationPitch(this->oRotation[0]);
				transformation = transformation * Matrix::CreateRotationRoll(this->oRotation[2]);
				transformation = transformation * Matrix::Create3DTranslation(fX, fY, fZ);

				this->oPosition[0] += transformation.fData[12];
				this->oPosition[1] += transformation.fData[13];
				this->oPosition[2] += transformation.fData[14];
			}

			void Transformable::Turn(float fPitch, float fYaw, float fRoll)
			{
				this->oRotation[0] += fPitch;
				if (this->oRotation[0] > 360) this->oRotation[0] = 0;
				this->oRotation[1] += fYaw;
				if (this->oRotation[1] > 360) this->oRotation[1] = 0;
				this->oRotation[2] += fRoll;
				if (this->oRotation[2] > 360) this->oRotation[2] = 0;
			}

			void Transformable::Scale(float fScaleX, float fScaleY, float fScaleZ)
			{
				this->oScale[0] += fScaleX;
				this->oScale[1] += fScaleY;
				this->oScale[2] += fScaleZ;
			}

			Matrix Transformable::GetLocalMatrix()
			{
				Matrix localMatrix;

				localMatrix = Matrix::Create3DTranslation(this->oPosition[0], this->oPosition[1], this->oPosition[2]) *
							  Matrix::CreateRotationYaw(this->oRotation[1]) * 
							  Matrix::CreateRotationPitch(this->oRotation[0]) * 
							  Matrix::CreateRotationRoll(this->oRotation[2]) *
							  Matrix::Create3DScale(this->oScale[0], this->oScale[1], this->oScale[2]);

				return localMatrix;
			}
		}
	}
}